﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using System.Reflection;
using System.Xml;
using VNet.VisiSuite.Common.Logger;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
using VNet.VisiSuite.Common.Helper;
using VNet.VisiSuite.Service.Proxy;
using VNet.VisiSuite.Service.Contact.Message.Base;
using System.Drawing;
using VNet.VisiSuite.Common;
using VNet.VisiSuite.VisiCentral.Common;

using Infragistics.Themes;
using Microsoft.Win32;
using System.Windows.Threading;

namespace VNet.VisiSuite.VisiCentral
{
    public partial class App : Application
    {
        private Mutex _mutex;
        private static string _application_name = null;
        private static Version _application_version = null;

        public static Version PublishedVersion()
        {
            if (_application_version == null)
            {
                XmlDocument xmlDoc = new XmlDocument();
                Assembly asmCurrent = System.Reflection.Assembly.GetExecutingAssembly();
                string executePath = new Uri(asmCurrent.GetName().CodeBase).LocalPath;

                xmlDoc.Load(executePath + ".manifest");
                string retval = string.Empty;
                if (xmlDoc.HasChildNodes)
                {
                    retval = xmlDoc.ChildNodes[1].ChildNodes[0].Attributes.GetNamedItem("version").Value.ToString();
                }
                _application_version = new Version(retval);
            }
            return _application_version;
        }

        public static string ApplicationName()
        {
            if (_application_name == null)
            {
                AssemblyProductAttribute product = (AssemblyProductAttribute)AssemblyProductAttribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyProductAttribute));
                _application_name = product.Product;
            }
            return _application_name;
        }

        public static string ApplicationNameAndVersion()
        {
            return string.Format("{0} v{1}", ApplicationName(), PublishedVersion().ToString());
        }

        public static void setStartup()
        {
#if !DEBUG
            if (RegistryHelper.isRunAtStartup())
            {
                // The path to the key where Windows looks for startup applications
                RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);

                //Path to launch shortcut
                Assembly asmCurrent = System.Reflection.Assembly.GetExecutingAssembly();
                string executePath = new Uri(asmCurrent.GetName().CodeBase).LocalPath;
                rk.SetValue("VisiCentral", executePath);
            }
#endif
        }

        protected override void OnStartup(StartupEventArgs theArgs)
        {
            base.OnStartup(theArgs);

            bool new_instance = false;
            _mutex = new Mutex(true, ApplicationName(), out new_instance);  //Creates a mutex for the application

            if (!new_instance)
            {
                FocusApp();
                Application.Current.Shutdown();  //Shutdown when a new mutex with the same name is created
            }
            else
            {
                Version ver = PublishedVersion();
                string msg = ApplicationName() + " " + ver.ToString() + " started.";
                FileLog.Info(msg);
                setStartup();
            }

            // Log all unhandled exceptions.
            this.Dispatcher.UnhandledException += OnDispatcherUnhandledException;
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnCurrentDomainUnhandledException);

            ThemeManager.ApplicationTheme = new MetroTheme() { StyleMicrosoftControls = true };

            DownloadLogoImage();

#if DEBUGx
            // TODO: Remove the line below on final build
            // Generate test data
            GenerateTestData();
#endif

        }

        private static void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            try
            {
                FileLog.Fatal("Unhandled exception: ", e.Exception);
            }
            catch
            {
                // to prevent recursion.
            }
        }

        static private void OnCurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            try
            {
                Exception ex = (Exception)e.ExceptionObject;
                FileLog.Fatal("Unhandled domain exception: ", ex);
            }
            catch
            {
                // to prevent recursion.
            }
        }

        [DllImport("user32.dll")]
        public static extern bool ShowWindowAsync(HandleRef hWnd, int nCmdShow);
        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr WindowHandle);
        public const int SW_RESTORE = 9;

        private bool FocusApp()
        {
            Process[] processes = Process.GetProcessesByName(ApplicationName());
            if (processes.Length > 0)
            {
                IntPtr hwnd = IntPtr.Zero;
                hwnd = processes[0].MainWindowHandle;
                ShowWindowAsync(new HandleRef(null, hwnd), SW_RESTORE);
                SetForegroundWindow(hwnd);
                return true;
            }
            return false;
        }

        public static void DownloadLogoImage()
        {
            if (!RegistryHelper.CheckRegistryInstallKeyExist())
                return;

            var client = new VNetVisiSuiteSecurityContractClient();
            var reg = RegistryHelper.OpenRegistryVisi(CommonConstants.RegistryVisiSuite, false);
            var request = new GetDataRequest { DataDescription = reg.GetValue(CommonConstants.RegistryInstallKey).ToString() };
            reg.Close();

            var response = client.DownloadLogoImage(request);

            if (!response.Success || response.Data == null)
                return;

            Bitmap bitmapImage = response.Data != null ? (Bitmap)ImageHelper.ConvertByteArrayToImage(response.Data.Image) : null;
            var localFilePath = FileHelper.Resolution(bitmapImage, FileHelper.GetExtension(response.Data.FileName), response.Data.FileName);
            Constants.StaticData.LogoPath = localFilePath;

        }

#if DEBUGx
        // TODO: Remove this region below on final build.
        #region VisiCentral Test Data

        /// <summary>
        /// Generates the test data for visi central application.
        /// </summary>
        public static void GenerateTestData()
        {
            if (!RegistryHelper.CheckRegistryInstallKeyExist())
                return;

            // Create initial data
            var client = new VNetVisiSuiteContractClient();
            var response = client.CreateDataTest();

            // Create a timer dispatcher to regularly call service to insert production history at 30 second intervals
            var timer = new DispatcherTimer(new TimeSpan(0, 0, 30), DispatcherPriority.Normal, delegate
            {
                client.CreateProductionHistoryAtInterval();
            }, Application.Current.Dispatcher);
        }

        #endregion
#endif
    }
}